package main

import (
	"container/list"
	"encoding/json"
	"fmt"
	"log"
	"strings"
	"time"

	"github.com/coreos/etcd/client"
	"golang.org/x/net/context"
)

//监听路径常量
//const ETCD_WATCH_PATH = "registry/pods/default/"
const ETCD_WATCH_PATH = "registry/pods/"

//删除map元素 delete(pc,"qingdao")
type EtcdMaster struct {
	members map[string]*list.List
	KeysAPI client.KeysAPI
}

//
type Member struct {
	IP      string
	AppName string
	Port    string
	HostIP  string
	Key     string
	//注册
	ClientId string //注册的客户端
}

func NewEtcdMaster(endpoints string) *EtcdMaster {
	etcList := strings.Split(endpoints, ",")
	cfg := client.Config{
		Endpoints:               etcList,
		Transport:               client.DefaultTransport,
		HeaderTimeoutPerRequest: time.Second,
	}
	etcdClient, err := client.New(cfg)
	if err != nil {
		log.Fatal("Error: cannot connec to etcd:", err)
		mainStatic.CHECK_RESTART = true
		fmt.Print("====cannot connec to etcd=====(11)=========================")
	}
	master := &EtcdMaster{
		members: make(map[string]*list.List),
		KeysAPI: client.NewKeysAPI(etcdClient),
	}

	return master
}

//初始化处理已存在的Pod的信息
func (m *EtcdMaster) InitPodWorker() {
	//获取Pod的路径
	_val, err := m.KeysAPI.Get(context.Background(), ETCD_WATCH_PATH+"default/", nil)
	if err != nil {
		log.Fatal("Error: InitPodWorker:", err)
		fmt.Print("=========(9)=========================")
		mainStatic.CHECK_RESTART = true

	}
	//fmt.Println(_val.Node.Nodes[0].Value)
	//var nodeValue map[string]interface{}
	for i := 0; i < _val.Node.Nodes.Len(); i++ {
		m.SwapPodInfoWorker(_val.Node.Nodes[i].Key, _val.Node.Nodes[i].Value)
	}

}

//把POD信息缓存起来
func (m *EtcdMaster) AddWorker(key string, info *PodWorkerInfo) {
	member := &Member{
		IP:      info.IP,
		AppName: info.AppName,
		Port:    info.Port,
		Key:     key,
	}
	m.AddPodModelWorker(member)

}

//查找到缓存的pod信息
func (m *EtcdMaster) SearchPodModelWorker(appname string, containerIp string, containerPort string) *Member {
	_data := m.members[appname]
	if _data == nil {
		return nil
	}

	for e := _data.Front(); e != nil; e = e.Next() {
		//fmt.Println("removing", e.Value)
		// l.Remove(e)
		_member := e.Value.(*Member)
		if _member.IP == containerIp && _member.Port == containerPort {
			return _member
		}
	}
	return nil
}

func (m *EtcdMaster) AddPodModelWorker(member *Member) {
	_data := m.members[member.AppName]
	if _data == nil {
		_data = list.New()
		m.members[member.AppName] = _data
	}

	for e := _data.Front(); e != nil; e = e.Next() {
		//fmt.Println("removing", e.Value)
		// l.Remove(e)
		_member := e.Value.(*Member)
		if _member.AppName == member.AppName && _member.IP == member.IP && _member.Port == member.Port {
			return
		}
	}
	//fmt.Println(member.AppName + "[" + member.IP + ":" + member.Port + "]")
	_data.PushBack(member)
}

//获取pod数据变化，提取Pod的IP，端口，应用名
func (m *EtcdMaster) SwapPodInfoWorker(key string, podjson string) {

	if mainStatic.CLIENT_LEADER == nil {
		return
	}
	info := m.GetPodWokerInfo(podjson)
	if info == nil {
		m.DeletePodInfoWorker(key)
		return
	}
	memberInfo := &Member{AppName: info.AppName, IP: info.IP, Port: info.Port, HostIP: info.HostIP, Key: key}
	//加到leader分配注册队列
	mainStatic.CLIENT_LEADER.AddDataEmptyQueue(memberInfo)
}

//从pod提取信息
func (m *EtcdMaster) GetPodWokerInfo(podjson string) *PodWorkerInfo {

	var nodeValue map[string]interface{}
	if err := json.Unmarshal([]byte(podjson), &nodeValue); err != nil {
		panic(err)
		mainStatic.CHECK_RESTART = true

		fmt.Print("=========(10)=========================")
		return nil
	}
	//metadata->labels->appname
	if nodeValue["metadata"] == nil {
		return nil
	}

	metadata := nodeValue["metadata"].(map[string]interface{})
	if metadata["labels"] == nil {
		return nil
	}

	labels := metadata["labels"].(map[string]interface{})
	if labels["servicename"] == nil {

		return nil
	}
	appname := labels["servicename"].(string)

	if labels["serviceport"] == nil {
		return nil
	}
	serviceport := labels["serviceport"].(string)

	//服务来源 [微服务]
	if labels["source"] == nil {
		return nil
	}

	if nodeValue["status"] == nil {
		return nil
	}

	if nodeValue["status"] == nil {
		return nil
	}

	status := nodeValue["status"].(map[string]interface{})

	if status["phase"] == nil || status["hostIP"] == nil || status["podIP"] == nil {
		return nil
	}
	phase := status["phase"].(string)
	hostIP := status["hostIP"].(string)
	podIP := status["podIP"].(string)

	if phase != "Running" || hostIP == "" || podIP == "" || serviceport == "" {
		return nil
	}

	info := &PodWorkerInfo{}
	info.AppName = appname
	info.HostIP = hostIP
	info.IP = podIP
	info.Port = serviceport

	return info

}

//删除ETCD的数据
func (m *EtcdMaster) DeleteEtcdMemberPath(member *Member) {

	path := mainStatic.ETCD_HV_WATCH_PATH + "/" + member.ClientId + "/" + member.AppName + ":" + member.IP + ":" + member.Port + "/"
	m.DeleteEtcdPath(path)
}

//删除ETCD的目录
func (m *EtcdMaster) DeleteEtcdPath(path string) {
	api := m.KeysAPI
	////客户端下线处理
	resp, err := api.Get(context.Background(), path, nil)
	if err != nil {
		return
	}
	m.DeleteEtcdLevelNode(resp.Node)

}

//删除ETCD的节点
func (m *EtcdMaster) DeleteEtcdLevelNode(cnode *client.Node) {
	//fmt.Println(cnode.Nodes)
	//fmt.Println(len(cnode.Nodes))
	api := m.KeysAPI
	nodes := cnode.Nodes
	if nodes == nil || len(nodes) == 0 {
		//fmt.Println("delete:" + cnode.Key)
		deleteOptions := &client.DeleteOptions{}
		deleteOptions.Dir = cnode.Dir
		_, err := api.Delete(context.Background(), cnode.Key, deleteOptions)
		if err != nil {
			fmt.Println(err)
		}
		return
	}

	for _, node := range nodes {
		m.DeleteEtcdLevelNode(node)
	}
	//fmt.Println(">>>delete:" + cnode.Key)

	deleteOptions := &client.DeleteOptions{}
	deleteOptions.Dir = cnode.Dir
	_, err := api.Delete(context.Background(), cnode.Key, deleteOptions)
	if err != nil {
		fmt.Println(err)
	}

}

//删除Pod信息
func (m *EtcdMaster) DeletePodInfoWorker(key string) {
	if mainStatic.CLIENT_LEADER == nil {
		return
	}
	member := mainStatic.CLIENT_LEADER.SearchClientData(key)
	if member == nil {
		fmt.Println("########没有找到要删除的记录############")
		return
	}

	mainStatic.CLIENT_LEADER.DeleteClientData(member)

}

//监控重启
func (m *EtcdMaster) WatchRestart() {

	api := m.KeysAPI
	api.Delete(context.Background(), ETCD_WATCH_PATH+"CLIENT_KEY/", nil)
	for {

		if mainStatic.CHECK_RESTART {

			//api.Delete(ETCD_WATCH_PATH + "CLIENT_KEY/")
			//pod生成
			_, err := api.Update(context.Background(), ETCD_WATCH_PATH+"CLIENT_KEY/", CLIENT_KEY)
			if err != nil {
				api.Create(context.Background(), ETCD_WATCH_PATH+"CLIENT_KEY/", CLIENT_KEY)
			}
			//分布式/高可用
			_, err = api.Update(context.Background(), mainStatic.ETCD_HV_WATCH_PATH+"/CLIENT_KEY/", CLIENT_KEY)
			if err != nil {
				api.Create(context.Background(), mainStatic.ETCD_HV_WATCH_PATH+"/CLIENT_KEY/", CLIENT_KEY)
			}

			break
		}
		time.Sleep(time.Second * 1)
	}

}

//监听分布式的工作
func (m *EtcdMaster) WatchHvWokers() {
	api := m.KeysAPI

	watcher := api.Watcher(mainStatic.ETCD_HV_WATCH_PATH+"/"+CLIENT_KEY+"/", &client.WatcherOptions{
		Recursive: true,
	})

	//m.DeleteEtcdPath(mainStatic.ETCD_HV_WATCH_PATH + "/134.132.93.208-1476864067574047800")

	//api.Delete(context.Background(), mainStatic.ETCD_HV_WATCH_PATH+"/134.132.93.208-1476864276465995800/test:190.0.0.1:80", nil)

	//resp, _ := api.Get(context.Background(), mainStatic.ETCD_HV_WATCH_PATH+"/134.132.93.208-1476863792530316200/", nil)
	//fmt.Println(resp.Node.Key)
	//fmt.Println(resp.Node.Value)

	for {
		res, err := watcher.Next(context.Background())
		//重启要求
		if mainStatic.CHECK_RESTART == true {
			return
		}
		if err != nil {
			log.Println("Error WatchHvWokers:", err)
			fmt.Print("=========(5)=========================")
			mainStatic.CHECK_RESTART = true
			break
		}
		//fmt.Println(" \n action:  " + res.Action + " key:" + res.Node.Key + " \nvalue:" + res.Node.Value + " \n time:" + time.Now().String())

		if res.Action == "expire" {

		} else if res.Action == "delete" {
			keyM := strings.Split(res.Node.Key, "/")
			go m.RemoveRegisterHvPod(keyM[len(keyM)-1])
		} else if res.Action == "create" {
			keyM := strings.Split(res.Node.Key, "/")
			go m.RegisterHvPod(keyM[len(keyM)-1], res.Node.Value)
		}
	}
}

func (m *EtcdMaster) AddEtcdHvInfo(member *Member) {
	path := mainStatic.ETCD_HV_WATCH_PATH + "/" + member.ClientId + "/" + member.AppName + ":" + member.IP + ":" + member.Port
	valjson := make(map[string]string)
	valjson["hostIP"] = member.HostIP
	valb, _ := json.Marshal(valjson)
	api := m.KeysAPI
	api.Create(context.Background(), path, string(valb))
	/*
		if err != nil {
			fmt.Print("=========(6)=========================")
			fmt.Println(err)
			mainStatic.CHECK_RESTART = true

		}
	*/

}

//移除注册分配的Pod信息
func (m *EtcdMaster) RemoveRegisterHvPod(key string) {
	podModelMember := m.GetPodModelMember(key, "{}")
	if podModelMember == nil {
		return
	}

	fmt.Println("clientId[" + CLIENT_KEY + "]移除容器服务[" + podModelMember.AppName + ":" + podModelMember.IP + podModelMember.Port + "]")

	mainStatic.ETCD_ZK_MASTER.DeleteEtcdReisterZk(podModelMember)

}

//接受注册分配的Pod信息
func (m *EtcdMaster) RegisterHvPod(key string, value string) {

	podModelMember := m.GetPodModelMember(key, value)
	if podModelMember == nil {
		return
	}
	_podMember := m.SearchPodModelWorker(podModelMember.AppName, podModelMember.IP, podModelMember.Port)
	if _podMember == nil {
		m.AddPodModelWorker(podModelMember)
		_podMember = podModelMember
	}
	//设置注册客户端标记
	_podMember.ClientId = CLIENT_KEY

	fmt.Println(">>>clientId[" + CLIENT_KEY + "]注册容器服务[" + _podMember.AppName + ":" + _podMember.IP + _podMember.Port + "]")

	mainStatic.ETCD_ZK_MASTER.AddEtcdReisterZk(_podMember)
}

func (m *EtcdMaster) GetPodModelMember(key string, value string) *Member {
	podkey := strings.Split(key, ":")
	if len(podkey) != 3 {
		return nil
	}
	//fmt.Println("@@@@@@@@@@@@value:" + value)
	var nodeValue map[string]interface{}
	if err := json.Unmarshal([]byte(value), &nodeValue); err != nil {
		panic(err)

		return nil
	}

	//	clinetId := CLIENT_KEY
	hostIP := ""
	if nodeValue["hostIP"] != nil {
		hostIP = nodeValue["hostIP"].(string)
	}
	appname := podkey[0]
	podIP := podkey[1]
	serviceport := podkey[2]

	member := &Member{
		IP:      podIP,
		AppName: appname,
		Port:    serviceport,
		HostIP:  hostIP,
		//ClientId: clinetId, //注册的客户端
	}
	return member
}

//监听
func (m *EtcdMaster) WatchWorkers() {
	api := m.KeysAPI
	watcher := api.Watcher(ETCD_WATCH_PATH, &client.WatcherOptions{
		Recursive: true,
	})
	//监听本身client的目录
	//go m.WatchHvWokers()
	////起动监控重启线程
	go m.WatchRestart()
	for {
		res, err := watcher.Next(context.Background())
		//重启要求
		if mainStatic.CHECK_RESTART {
			return
		}

		if err != nil {
			log.Println("Error watch workers:", err)
			fmt.Print("=========(4)=========================")
			mainStatic.CHECK_RESTART = true
			break
		}

		//fmt.Println(" \n action:  " + res.Action + " key:" + res.Node.Key + " \nvalue:" + res.Node.Value + " \n time:" + time.Now().String())
		if res.Action == "expire" {
		} else if res.Action == "delete" {
			go m.DeletePodInfoWorker(res.Node.Key)
		} else if res.Action == "compareAndSwap" {
			go m.SwapPodInfoWorker(res.Node.Key, res.Node.Value)

		}
	}

}
